/*
 * Area.hpp
 *
 *  Created on: 15/11/2011
 *      Author: Tales
 */

#ifndef YEP_VIDEO_Area_HPP
#define YEP_VIDEO_Area_HPP

#include <SDL.h>
#include "Vector2.hpp"
#include <math.h>

namespace yep
{
    /**
     * @brief Represents a Area.
     *
     * This classes encapsulates a SDL_Rect, having compatibility with all
     *  the function using SDL_Rect. It has all needed methods, contructors and cast operations
     *  to peform convertions to and from SDL_Rect, SDL_Rect* and Point<T>.
     **/
    class Rect
    {
    public:
        /**
         * @brief Contructs an empty Area
         **/
        Rect()
        {
            internalArea = {0,0,0,0};
        }

        /**
         * @brief Contructs a Area using the given components
         **/
        Rect(Sint16 x, Sint16 y, Uint16 w, Uint16 h)
        {
            internalArea = {x, y, w, h};
        }

        /**
         * @brief Constructs a Area using the given Area
         **/
        Rect(const SDL_Rect &Area)
        {
            internalArea = Area;
        }

        /**
         * @brief Constructs a Area using a Vector2
         **/
        Rect(const Vector2 &point )
        {
            internalArea = {(Sint16)point.x, (Sint16)point.y, 0, 0};
        }

        /** @defgroup gettersAndSetters */
        /** @{ */
        /**
         * @brief gets the x
         **/
        Sint16 getX() const
        {
            return internalArea.x;
        }

        /**
         * @brief Getter/Setter
         **/
        Sint16 &x()
        {
            return internalArea.x;
        }

        /**
         * @brief gets the y
         **/
        Sint16 getY() const
        {
            return internalArea.y;
        }

        /**
         * @brief Getter/Setter
         **/
        Sint16 &y()
        {
            return internalArea.y;
        }

        /**
         * @brief gets X2
         **/
        Sint16 getX2() const
        {
            return internalArea.x+internalArea.w-1;
        }

        /**
         * @brief gets Y2
         **/
        Sint16 getY2() const
        {
            return internalArea.y+internalArea.h-1;
        }

        /**
         * @brief gets the w
         **/
        Uint16 &w()
        {
            return internalArea.w;
        }

        /**
         * @brief gets the w
         **/
        Uint16 getW() const
        {
            return internalArea.w;
        }
        /**
         * @brief gets the h
         **/
        Uint16 getH() const
        {
            return internalArea.h;
        }
        /**
         * @brief gets the h
         **/
        Uint16 &h()
        {
            return internalArea.h;
        }

        /**
         * @brief Sets the x
         **/
        void setX(Sint16 value)
        {
            internalArea.x = value;
        }
        /**
         * @brief Sets the y
         **/
        void setY(Sint16 value)
        {
            internalArea.y = value;
        }
        /**
         * @brief Sets the w
         **/
        void setW(Uint16 value)
        {
            internalArea.w = value;
        }
        /**
         * @brief Sets the h
         **/
        void setH(Uint16 value)
        {
            internalArea.h = value;
        }

        /**
         * @brief Gets the position vector
         * @return the position.
         */
        Vector2 getPosition()
        {
        	return Vector2((double)x(), (double)y());
        }

        /**
         * @brief Sets the position
         * @param value the new position.
         */
        void setPosition(const Vector2 &value)
        {
        	x() = (Sint16)value.x;
        	y() = (Sint16)value.y;
        }

        /**
         * @brief Get size
         * @return the size vector
         */
        Vector2 getSize()
        {
        	return Vector2((double)w(), (double)h());
        }

        void setSize(const Vector2 &value)
        {
        	w() = (Uint16)value.x;
        	h() = (Uint16)value.y;
        }

        /// @}
        /**
         * @brief Casts to a SDL_Rect.
         *
         * If the returned value changes, the Area itself also changes
         **/
        operator SDL_Rect&()
        {
            return internalArea;
        }

        /**
         * @brief The const version of the operator SDL_Rect&
         **/
        operator const SDL_Rect&() const
        {
            return internalArea;
        }

        /**
         * @brief Casts to SDL_Rect*.
         *
         * If the returned value changes, the Area itself also changes
         **/
        operator SDL_Rect*()
        {
            return &internalArea;
        }

        /**
         * @brief The const version of the operator SDL_Rect*
         **/
        operator const SDL_Rect*() const
        {
            return &internalArea;
        }

        operator Vector2() const
		{
        	return Vector2(internalArea.x, internalArea.y);
		}

    private:
        SDL_Rect internalArea;
    };
}

#endif // YEP_VIDEO_Area_HPP
